home *** CD-ROM | disk | FTP | other *** search
- #define NAME "CheckX"
- #define REVISION "85"
- #define DISTRIBUTION "(Freeware) "
- #define DATE "12.07.2001"
- #define VERSION "1"
- #define AUTHOR "by Dirk Stöcker <stoecker@epost.de>"
-
- /*
- This program scans for crunched, linked files and archived files. It
- decrunches them and saves the result files to another directory-tree.
- The scanning routines are recursive and thus check really all stuff.
-
- The program must be compiled and linked without startup-code. You can set
- the pure file protection bit and make it resident, because it is multi-
- reentrant (no global variables, except library bases).
- */
-
- /* Programmheader
-
- Name: CheckX
- Author: SDI
- Distribution: Freeware
- Description: scans, decrunches and dearchives files
- Compileropts: -
- Linkeropts: -l xpkmaster xadmaster amiga -gsi
-
- 1.0 14.12.96 : first Version
- 1.1 28.12.96 : moved PassRequest into xpkmaster.library
- 1.2 12.02.97 : now also decrunches Exe-Files
- 1.3 15.06.97 : added length output as test
- 1.4 21.11.97 : renamed from Decrunch, got really new program
- 1.5 22.11.97 : bug-fixes
- 1.6 29.11.97 : added unarchiving feature
- 1.7 30.11.97 : bug-fixes
- 1.8 06.12.97 : xpkmaster.library now only required with ASKPWD option
- 1.9 07.12.97 : Added archive copy for weird archive names, better error
- codes
- 1.10 08.12.97 : fixed error codes a bit
- 1.11 11.12.97 : disabled DOS requests, added Zip-Archives, added TaskID
- to temporary filenames
- 1.12 12.12.97 : added Arc, ZOO and LhASFX archives
- 1.13 13.12.97 : fixed Arc recognition
- 1.14 19.12.97 : deletes copied arc before scan
- 1.15 22.12.97 : crunched archives are unarchived correctly now
- 1.16 02.01.98 : opens dos.library itself, no startup-code required
- 1.17 23.01.98 : added disk crunchers
- 1.18 24.01.98 : some fixes
- 1.19 01.02.98 : little bug-fix in argument-option use
- 1.20 06.02.98 : better error output, added automount
- 1.21 08.02.98 : little bug-fix
- 1.22 10.02.98 : fixed archive copy conditions, added PRINTALL
- 1.23 12.02.98 : fixed help text, bug fixes with unlinking and FreeMem
- 1.24 13.02.98 : added unstripping
- 1.25 04.03.98 : added PRINTEXEC
- 1.26 13.03.98 : added high density DMS support
- 1.27 19.03.98 : added LOUD keyword
- 1.28 23.03.98 : RDx no longer depends on archive depth, but on dddepth
- 1.29 10.04.98 : bug fixes
- 1.30 26.04.98 : bug fixes
- 1.31 09.05.98 : now uses no longer adress 4 for SysBase
- 1.32 31.05.98 : better output
- 1.33 04.06.98 : added HEADER addition for address files
- 1.34 08.08.98 : bug fix with SAVE
- 1.35 24.09.98 : added xvs.library virus checks
- 1.36 18.10.98 : xvs is opened global and only once
- 1.37 30.10.98 : renamed from CheckXFD
- 1.38 11.11.98 : fixed format drive bug using a delay and an error report
- 1.39 14.11.98 : format error with AUTOMOUNT removed
- 1.40 16.11.98 : removed HEADER addition stuff
- 1.41 18.11.98 : better RDx: access and mount
- 1.42 23.11.98 : fixed bug with hunk stripping
- 1.43 29.12.98 : now prints an error, when virus detection is turned off,
- added time calculation and output
- 1.44 31.12.98 : little bug fix
- 1.45 06.02.99 : bug fixes, added xadmaster.library stuff, removed LOUD
- and internal DMS call
- 1.46 09.02.99 : removed internal LZX call
- 1.47 11.02.99 : now uses assembler startcode allocating a bigger stack
- 1.48 14.02.99 : bug-fixes for nocylinder archivers (PackDev)
- 1.49 16.02.99 : fixed strip option (don't know, where the error was :-)
- 1.50 21.02.99 : removed internal Zoom call and disk-archiver stuff
- 1.51 22.02.99 : fixed archiver call for remaining non-XAD archivers, added
- empty file check
- 1.52 23.02.99 : fixed StartCode return value
- 1.53 24.02.99 : forgot empty check for archived files
- 1.54 08.03.99 : old archiver calling did not work, when file was XAD
- unarchived
- 1.55 26.03.99 : prints error, when logfile cannot be created
- 1.56 30.03.99 : added bootblock scanning for unarchived disks
- 1.57 16.05.99 : bug fix with unlinked file save
- 1.58 17.07.99 : removed internal LhA Support
- 1.59 30.07.99 : bug fix with file name prints
- 1.60 03.08.99 : added DEBUG option
- 1.61 05.08.99 : added XVS SelfTest and MemoryTest
- 1.62 19.08.99 : added error summary, again fixed name problem
- 1.63 14.09.99 : solved big memory loss problem (did not free xadArchiveInfo),
- added logfile comment
- 1.64 17.10.99 : removed external archiver calls, added QUIET
- 1.65 24.11.99 : now sets nice return values
- 1.66 26.11.99 : tries reading again before giving read error
- 1.67 03.12.99 : bug fix in name printing
- 1.68 04.12.99 : tries again opening files.
- 1.69 16.12.99 : added NOSILENT Option
- 1.70 15.01.00 : files from disc archives are extracted directly now,
- removed double read tries
- 1.71 16.01.00 : fixed error messages for disk unarchiving
- 1.72 12.02.00 : added support for ADF images
- 1.73 13.02.00 : bug fix for disk archives
- 1.74 09.03.00 : now detects XADFIF_NOFILENAME and XADFIF_NOUNCRUNCHSIZE
- 1.75 05.04.00 : fixed bug with XADFIF_NOFILENAME
- 1.76 26.04.00 : added size checkout for XADFIF_NOUNCRUNCHSIZE
- 1.77 05.06.00 : added support for multiple filesystems, removed NODOS and
- diskerr errors, always prints FS-type now.
- 1.78 24.07.00 : bug fix
- 1.79 27.07.00 : bug fix with multi FS support
- 1.80 14.09.00 : added SAVEALL keyword
- 1.81 25.03.01 : added support for crypted archives and large archive scan
- 1.82 05.04.01 : fixed Enforcer hit
- 1.83 08.04.01 : empty file got warning
- 1.84 18.04.01 : added texts in case libraries could not be opened
- 1.85 12.07.01 : added sector checks, reduced final file size
- */
-
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/xfdmaster.h>
- #include <proto/xadmaster.h>
- #include <proto/xpkmaster.h>
- #include <proto/intuition.h>
- #include <proto/xvs.h>
- #include <proto/utility.h>
- #include <libraries/xfdmaster.h>
- #include <dos/dostags.h>
- #include <dos/doshunks.h>
- #include <dos/filehandler.h>
- #include <exec/memory.h>
- #include "SDI_compiler.h"
-
- #define PARAM "FROM,LOG,SAVE/K,ALL/S,ASKPWD/S,PRINTALL/S,PRINTEXEC/S," \
- "NODECRUNCH/S,NOUNLINK/S,NOUNARCHIVE/S,NOUNTRACK/S," \
- "NOSILENT/S,NOSTRIP/S,NOVIRUS/S,DEBUG/S,QUIET/S," \
- "SAVEALL/S,SECTORCHECK/S"
-
- #define version "$VER: " NAME " " VERSION "." REVISION " (" DATE ") " DISTRIBUTION AUTHOR
-
- void RawPutChar(ULONG c);
-
- #ifdef __SASC
- #pragma libcall SysBase RawPutChar 204 001
- #elif defined(__GNUC__)
- #define RawPutChar(c) LP1NR(204, RawPutChar, ULONG, c, d0, , SysBase)
- #else
- #pragma amicall(SysBase,0x204,RawPutChar(d0))
- #endif
-
- struct FileData {
- struct CrunchMemList * fd_MemList;
- #ifdef __SASC
- struct xfdMasterBase * fd_xfdMasterBase;
- struct xvsBase * fd_xvsBase;
- struct xadMasterBase * fd_xadMasterBase;
- struct DosLibrary * fd_DOSBase;
- struct ExecBase * fd_SysBase;
- #endif
- STRPTR fd_Name;
- STRPTR fd_Memory; /* for bootblock checks */
- BPTR fd_LogFileFH;
- BPTR fd_ArcFileFH;
- ULONG fd_SaveDirL;
- ULONG fd_Flags;
- ULONG fd_NumVirus;
- ULONG fd_NumSectors;
- ULONG fd_CHKXErrors;
- ULONG fd_CHKXWarnings; /* not printed yet */
- ULONG fd_XFDErrors;
- ULONG fd_XADErrors;
- ULONG fd_CorruptedArchives;
- BYTE fd_RecurseDepth;
- UBYTE fd_LinkNum;
- UBYTE fd_ArchiveDepth;
- };
-
- typedef struct xadMasterBase XADMASTERBASE;
- typedef struct xfdMasterBase XFDMASTERBASE;
- typedef struct xvsBase XVSBASE;
-
- #ifdef __SASC
- static struct ExecBase *sysbase;
- #define XpkBase xpkbase
- #define ASSIGN_XPK
- #define IntuitionBase intuitionbase
- #define ASSIGN_INT
- #define UtilityBase utilitybase
- #define ASSIGN_UTIL
- #define xfdMasterBase fd->fd_xfdMasterBase
- #define ASSIGN_SYS sysbase = fd->fd_SysBase = (*((struct ExecBase **) 4));
- #define SysBase fd->fd_SysBase
- #define DOSBase fd->fd_DOSBase
- #define ASSIGN_DOS DOSBase = dosbase;
- #define xvsBase fd->fd_xvsBase
- #define xadMasterBase fd->fd_xadMasterBase
- #else
- struct Library * XpkBase;
- struct IntuitionBase * IntuitionBase;
- struct UtilityBase * UtilityBase;
- #define ASSIGN_XPK XpkBase = xpkbase;
- #define ASSIGN_INT IntuitionBase = intuitionbase;
- #define ASSIGN_UTIL UtilityBase = utilitybase;
- #define ASSIGN_SYS SysBase = (*((struct ExecBase **) 4));
- #define ASSIGN_DOS DOSBase = dosbase;
- struct xfdMasterBase * xfdMasterBase;
- struct xvsBase * xvsBase;
- struct xadMasterBase * xadMasterBase;
- struct DosLibrary * DOSBase;
- struct ExecBase * SysBase;
- #endif
-
- struct Args {
- STRPTR from;
- STRPTR log;
- STRPTR save;
- ULONG all;
- ULONG askpwd;
- ULONG printall;
- ULONG printexec;
- ULONG nodecrunch;
- ULONG nounlink;
- ULONG nounarchive;
- ULONG nountrack;
- ULONG nosilent;
- ULONG nostrip;
- ULONG novirus;
- ULONG debug;
- ULONG quiet;
- ULONG saveall;
- ULONG sectorcheck;
- };
-
- struct CrunchMemList {
- struct CrunchMemList * cml_Next;
- APTR cml_MemoryRegion;
- ULONG cml_MemorySize;
- };
-
- #define CHECKXFLAG_SAVE (1<< 0)
- #define CHECKXFLAG_ALL (1<< 1)
- #define CHECKXFLAG_ASKPWD (1<< 2)
- #define CHECKXFLAG_PRINTALL (1<< 3)
- #define CHECKXFLAG_PRINTEXEC (1<< 4)
- #define CHECKXFLAG_NODECRUNCH (1<< 5)
- #define CHECKXFLAG_NOUNLINK (1<< 6)
- #define CHECKXFLAG_NOUNARCHIVE (1<< 7)
- #define CHECKXFLAG_NOUNTRACK (1<< 8)
- #define CHECKXFLAG_NOSTRIP (1<< 9)
- #define CHECKXFLAG_DEBUG (1<<10)
- #define CHECKXFLAG_QUIET (1<<11)
- #define CHECKXFLAG_SAVEALL (1<<12)
- #define CHECKXFLAG_SECTORCHECK (1<<13)
-
- #define CHECKXFLAG_XVSLIB (1<<20)
-
- #define CHKXCALLFLAGS (CHECKXFLAG_SAVE|CHECKXFLAG_ALL| \
- CHECKXFLAG_ASKPWD|CHECKXFLAG_PRINTALL| \
- CHECKXFLAG_PRINTEXEC|CHECKXFLAG_NODECRUNCH| \
- CHECKXFLAG_NOUNLINK|CHECKXFLAG_NOUNARCHIVE| \
- CHECKXFLAG_NOUNTRACK|CHECKXFLAG_NOSTRIP| \
- CHECKXFLAG_DEBUG|CHECKXFLAG_QUIET| \
- CHECKXFLAG_XVSLIB|CHECKXFLAG_SAVEALL| \
- CHECKXFLAG_SECTORCHECK)
-
- #define CHKXSAVEFLAGS (CHECKXFLAG_LINKED|CHECKXFLAG_CRUNCHED| \
- CHECKXFLAG_STRIPPED|CHECKXFLAG_SAVEALL)
-
- #define CHECKXFLAG_NAMEPRINTED (1<<26)
- #define CHECKXFLAG_CRUNCHED (1<<27)
- #define CHECKXFLAG_LINKED (1<<28)
- #define CHECKXFLAG_ADDRESS (1<<29)
- #define CHECKXFLAG_NOFREEMEM (1<<30)
- #define CHECKXFLAG_STRIPPED (1<<31)
-
- #define CHXWARN_OFFSET 30
- #define XADERR_OFFSET 0x100
- #define XFDERR_OFFSET 0x200
-
- #define CHKXERR_NOMEMORY 1
- #define CHKXERR_EXAMINEERR 2
- #define CHKXERR_OPENERR 3
- #define CHKXERR_READ 4
- #define CHKXERR_SCANERR 5
- #define CHKXERR_BREAK 6
- #define CHKXERR_OPENDIR 7
- #define CHKXERR_RESOURCE 8
- #define CHKXERR_NOBOOTVIRUS 9
- #define CHKXERR_WRITE 10
- #define CHKXERR_NOVIRUS 11
- #define CHKXERR_NOMEMORYARC 12
- #define CHKXERR_NOSECTOR 13
-
- #define CHKXWARN_NOVIRUS 31
- #define CHKXWARN_XVSSELFTEST 32
- #define CHKXWARN_MEMVIRUS 33
- #define CHKXWARN_EMPTY 34
-
- static void SetLogComment(struct FileData *, STRPTR);
- static LONG DoDirectoryScan(struct FileData *, STRPTR, STRPTR);
- static LONG DoFileOpen(struct FileData *);
- static LONG DoGetVirus(struct FileData *, APTR, ULONG);
- static LONG DoFileUnArchive(struct FileData *, APTR, ULONG);
- static LONG DoFileUnLink(struct FileData *, APTR, ULONG);
- static LONG DoFileUnCrunch(struct FileData *, APTR, ULONG);
- static LONG DoFileStrip(struct FileData *, APTR, ULONG);
- static void PrintCHKXFile(struct FileData *);
- static void PrintCHKXErr(struct FileData *, LONG);
- static void PrintCHKXTxt(struct FileData *, STRPTR, ...);
- static LONG AddCrunchMemList(struct FileData *, APTR, ULONG);
- static void FreeCrunchMemList(struct FileData *, APTR);
- static LONG SaveUncrFile(struct FileData *, APTR, ULONG);
- static ULONG OpenParentDir(struct FileData *);
- static ULONG OpenNewDir(struct FileData *, STRPTR);
- static LONG DoSectorCheck(struct FileData *, APTR, ULONG, ULONG);
- static const struct Hook breakhook;
- static void clear(APTR, ULONG);
- static void SPrintF(STRPTR buf, STRPTR format, ...);
- static ASM(void) KPutC(REG(d0, ULONG c));
- static void KPrintf(STRPTR fmt, ...);
-
- /* All memory regions must be in mem list. All unneeded memory must be freed
- as fast as possible (after unlinking, decrunching), as well as the
- MemoryList structure.
-
- The program has a loop like scan routine system, which is called for
- every file:
-
- A) Scan files, directories and sub directories and call following for
- every file:
- 1) Check for viruses.
- 2) Test if it is an archive. When yes decrunch and start for every file
- with point 1.
- 3) Test if file is linked. When yes unlink and call point 1 for both
- parts.
- 4) Test if file is crunched. When yes, decrunch and start again with
- point 1.
- 5) Try stripping useless stuff. When successful start with point 1 again.
- 6) Possibly save file (with SAVE option) or end loop here.
- */
-
- /* main routine, do argument parsing */
- LONG start(void)
- {
- LONG error = RETURN_FAIL;
- struct FileData fd[1];
- struct DosLibrary *dosbase;
- struct Process *task;
-
- clear((STRPTR)fd, sizeof(struct FileData));
- ASSIGN_SYS
-
- /* test for WB and reply startup-message */
- if(!(task = (struct Process *) FindTask(0))->pr_CLI)
- {
- WaitPort(&task->pr_MsgPort);
- Forbid();
- ReplyMsg(GetMsg(&task->pr_MsgPort));
- return RETURN_FAIL;
- }
-
- if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
- {
- XFDMASTERBASE * xfdmasterbase;
-
- ASSIGN_DOS
- if((xfdmasterbase = (XFDMASTERBASE *) OpenLibrary("xfdmaster.library", 39)))
- {
- XADMASTERBASE *xadmasterbase;
-
- xfdMasterBase = xfdmasterbase;
- if((xadmasterbase = (XADMASTERBASE *) OpenLibrary("xadmaster.library", 10)))
- {
- struct Args Args;
- struct RDArgs *rda;
-
- xadMasterBase = xadmasterbase;
- clear((STRPTR)(&Args), sizeof(struct Args));
-
- if((rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
- {
- rda->RDA_ExtHelp = version; /* is removed by optimizer */
- rda->RDA_ExtHelp =
- "FROM source file or directory - may contain patterns\n"
- "LOG log file name\n"
- "SAVE directory, where decrunched files are saved\n"
- "ALL scan deep into directories\n"
- "ASKPWD ask for password when needed (needs xpkmaster.library)\n"
- "PRINTALL print all filenames\n"
- "PRINTEXEC print names of all executable files\n"
- "NODECRUNCH do not decrunch files with xfdmaster\n"
- "NOUNLINK do not unlink files with xfdmaster\n"
- "NOUNARCHIVE do not unarchive file archives\n"
- "NOUNTRACK do not unarchive track archives\n"
- "NOSILENT do not disable dos requests\n"
- "NOSTRIP do not strip useless hunks\n"
- "NOVIRUS do not scan with xvs.library for viruses\n"
- "DEBUG also output texts to serial debug engine\n"
- "QUIET do not output texts to console\n"
- "SAVEALL saves all files (also uncrunched) except address files\n"
- "SECTORCHECK checks the files for virus infected sectors\n";
-
- if(ReadArgs(PARAM, (LONG *) &Args, rda))
- {
- ULONG flags = 0, log = 0;
- XVSBASE *xvsbase = 0;
-
- if(!Args.from) Args.from = "#?";
- if(Args.all) flags |= CHECKXFLAG_ALL;
- if(Args.save) flags |= CHECKXFLAG_SAVE;
- if(Args.saveall) flags |= CHECKXFLAG_SAVEALL;
- if(Args.askpwd) flags |= CHECKXFLAG_ASKPWD;
- if(Args.printall) flags |= CHECKXFLAG_PRINTALL;
- if(Args.printexec) flags |= CHECKXFLAG_PRINTEXEC;
- if(Args.nodecrunch) flags |= CHECKXFLAG_NODECRUNCH;
- if(Args.nounlink) flags |= CHECKXFLAG_NOUNLINK;
- if(Args.nounarchive) flags |= CHECKXFLAG_NOUNARCHIVE;
- if(Args.nountrack) flags |= CHECKXFLAG_NOUNTRACK;
- if(Args.nostrip) flags |= CHECKXFLAG_NOSTRIP;
- if(Args.debug) flags |= CHECKXFLAG_DEBUG;
- if(Args.quiet) flags |= CHECKXFLAG_QUIET;
- if(Args.sectorcheck) flags |= CHECKXFLAG_SECTORCHECK;
-
- if(!Args.novirus)
- {
- if((xvsbase = (XVSBASE *) OpenLibrary("xvs.library", 33)))
- {
- flags |= CHECKXFLAG_XVSLIB;
- xvsBase = xvsbase;
- }
- }
-
- if(!Args.log || (log = Open(Args.log, MODE_READWRITE)))
- {
- APTR win;
- ULONG s1 = 0, s2 = 0, msecs;
- struct IntuitionBase *intuitionbase;
-
- win = task->pr_WindowPtr;
- if(!Args.nosilent)
- task->pr_WindowPtr = (APTR) -1;
- /* prevent dos requests */
-
- if(log)
- {
- SetFileSize(log, 0, OFFSET_BEGINNING);
- SetProtection(Args.log, FIBF_EXECUTE);
- SetLogComment(fd, Args.log);
- }
-
- fd->fd_Flags = flags | CHECKXFLAG_NAMEPRINTED; /* for possible warnings display */
- fd->fd_LogFileFH = log;
-
- if(!xvsbase)
- PrintCHKXErr(fd, CHKXWARN_NOVIRUS);
- else
- {
- struct xvsMemoryInfo *mi;
-
- if(!xvsSelfTest())
- PrintCHKXErr(fd, CHKXWARN_XVSSELFTEST);
-
- if((mi = (struct xvsMemoryInfo *) xvsAllocObject(XVSOBJ_MEMORYINFO)))
- {
- if(xvsSurveyMemory(mi))
- PrintCHKXErr(fd, CHKXWARN_MEMVIRUS);
-
- xvsFreeObject(mi);
- }
- }
-
- if((intuitionbase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37)))
- {
- ASSIGN_INT
- CurrentTime(&s1, &msecs);
- }
-
- ++fd->fd_RecurseDepth;
- error = DoDirectoryScan(fd, Args.from, Args.save) ? RETURN_FAIL : RETURN_OK;
- --fd->fd_RecurseDepth;
- fd->fd_Flags |= CHECKXFLAG_NAMEPRINTED; /* for result texts */
-
- task->pr_WindowPtr = win;
-
- if(intuitionbase)
- {
- CurrentTime(&s2, &msecs);
- s2 -= s1;
- s1 = s2 / 60;
- s2 %= 60;
- msecs = s1 / 60;
- s1 %= 60;
- PrintCHKXTxt(fd, "\nTime needed for check: %2ld:%02ld:%02ld", msecs, s1, s2);
- CloseLibrary((struct Library *) intuitionbase);
- }
- if(fd->fd_NumVirus && !fd->fd_NumSectors)
- PrintCHKXTxt(fd, "The scan detected %ld virus%s.", fd->fd_NumVirus, fd->fd_NumVirus > 1 ? "es" : "");
- else if(fd->fd_NumVirus && fd->fd_NumSectors)
- PrintCHKXTxt(fd, "The scan detected %ld virus%s and %ld defective sector%s.", fd->fd_NumVirus,
- fd->fd_NumVirus > 1 ? "es" : "", fd->fd_NumSectors, fd->fd_NumSectors > 1 ? "s" : "");
- else if(!fd->fd_NumVirus && fd->fd_NumSectors)
- PrintCHKXTxt(fd, "The scan detected %ld defective sector%s.", fd->fd_NumSectors,
- fd->fd_NumSectors > 1 ? "s" : "");
- if(fd->fd_CHKXErrors || fd->fd_XADErrors || fd->fd_XFDErrors || fd->fd_CorruptedArchives)
- PrintCHKXTxt(fd, "There were errors (CheckX/XFD/XAD/corrupted archives): %ld/%ld/%ld/%ld.",
- fd->fd_CHKXErrors, fd->fd_XFDErrors, fd->fd_XADErrors, fd->fd_CorruptedArchives);
- if(!error && (fd->fd_NumVirus || !xvsBase))
- {
- SetIoErr(0);
- error = RETURN_WARN;
- }
-
- if(log)
- Close(log);
- }
- else if(Args.log && !Args.quiet)
- Printf("Could not create logfile.\n");
-
- if(xvsbase)
- CloseLibrary((struct Library *) xvsbase);
- FreeArgs(rda);
- }
- else
- PrintFault(IoErr(), "CheckX");
- FreeDosObject(DOS_RDARGS, rda);
- }
- CloseLibrary((struct Library *) xadmasterbase);
- }
- else
- Printf("CheckX requires xadmaster.library version 10 or better.\n");
- CloseLibrary((struct Library *) xfdmasterbase);
- }
- else
- Printf("CheckX requires xfdmaster.library version 39 or better.\n");
- CloseLibrary((struct Library *) dosbase);
- }
-
- return error;
- }
-
- static void clear(STRPTR buf, ULONG size)
- {
- while(size--)
- *(buf++) = 0;
- }
-
- static void SetLogComment(struct FileData *fd, STRPTR name)
- {
- UBYTE com[30];
- struct MsgPort *TimerMP;
-
- if((TimerMP = CreateMsgPort()))
- {
- struct timerequest *TimerIO;
-
- if((TimerIO = (struct timerequest *) CreateIORequest(TimerMP,
- sizeof(struct timerequest))))
- {
- if(!OpenDevice("timer.device",UNIT_VBLANK,
- (struct IORequest *)TimerIO,0))
- {
- struct UtilityBase *utilitybase;
-
- TimerIO->tr_node.io_Command = TR_GETSYSTIME;
- DoIO((struct IORequest *) TimerIO);
- if((utilitybase = (struct UtilityBase *) OpenLibrary("utility.library",37)))
- {
- struct ClockData dat;
-
- ASSIGN_UTIL
- Amiga2Date(TimerIO->tr_time.tv_secs, &dat);
- SPrintF(com, "CheckX " VERSION "." REVISION " - %02ld.%02ld.%ld", dat.mday, dat.month, dat.year);
- CloseLibrary((struct Library *) utilitybase);
- SetComment(name, com);
- }
- CloseDevice((struct IORequest *) TimerIO);
- }
- DeleteIORequest(TimerIO);
- }
- DeleteMsgPort(TimerMP);
- }
- }
-
- /* This scans a directory and calls DoFileOpen for every file. It
- automatically creates SAVE destination directories when necessary. */
- static LONG DoDirectoryScan(struct FileData *fd, STRPTR name, STRPTR sav)
- {
- struct AnchorPath *APath;
- LONG error = CHKXERR_SCANERR;
- ULONG retval;
-
- if(!(fd->fd_Flags & CHECKXFLAG_SAVE) || !sav ||
- (fd->fd_SaveDirL = Lock(sav, SHARED_LOCK)))
- {
- if((APath = (struct AnchorPath *) AllocMem(sizeof(struct AnchorPath) +
- 512, MEMF_PUBLIC|MEMF_CLEAR)))
- {
- fd->fd_Name = APath->ap_Buf;
- APath->ap_Strlen = 256;
- for(retval = MatchFirst(name, APath); !retval;
- retval = MatchNext(APath))
- {
- if(APath->ap_Flags & APF_DIDDIR)
- {
- OpenParentDir(fd);
- APath->ap_Flags &= ~APF_DIDDIR; /* clear flag */
- }
- else if(APath->ap_Info.fib_DirEntryType > 0)
- {
- if(fd->fd_Flags & CHECKXFLAG_ALL)
- {
- OpenNewDir(fd, APath->ap_Info.fib_FileName);
- APath->ap_Flags |= APF_DODIR;
- }
- }
- else
- {
- fd->fd_Flags &= CHKXCALLFLAGS;
- fd->fd_LinkNum = 0;
- PrintCHKXErr(fd, DoFileOpen(fd));
-
- while(fd->fd_MemList)
- FreeCrunchMemList(fd, fd->fd_MemList->cml_MemoryRegion);
- }
- if((fd->fd_Flags & CHECKXFLAG_SAVE) && !fd->fd_SaveDirL)
- {
- error = CHKXERR_OPENDIR; break;
- }
- if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
- {
- error = CHKXERR_BREAK; break;
- }
- }
- MatchEnd(APath);
-
- if(retval == ERROR_NO_MORE_ENTRIES)
- error = 0;
-
- FreeMem(APath, sizeof(struct AnchorPath) + 512);
- }
- else
- error = CHKXERR_NOMEMORY;
-
- if(sav && fd->fd_SaveDirL)
- UnLock(fd->fd_SaveDirL);
- }
- else
- error = CHKXERR_OPENDIR;
-
- fd->fd_Flags |= CHECKXFLAG_NAMEPRINTED;
- if(error)
- PrintCHKXErr(fd, error);
-
- return error;
- }
-
- /* Open a file and call DoGetVirus to scan */
- static LONG DoFileOpen(struct FileData *fd)
- {
- struct FileInfoBlock *fib;
- LONG ret = 0;
-
- if((fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
- {
- ULONG fh;
-
- if((fh = Open(fd->fd_Name, MODE_OLDFILE)))
- {
- if(ExamineFH(fh, fib))
- {
- APTR mem;
-
- if(!fib->fib_Size)
- ret = CHKXWARN_EMPTY;
- else if((mem = AllocMem(fib->fib_Size, MEMF_ANY)))
- {
- if(Read(fh, mem, fib->fib_Size) != fib->fib_Size)
- ret = CHKXERR_READ;
-
- if(!ret && !(ret = AddCrunchMemList(fd, mem, fib->fib_Size)))
- {
- if((fd->fd_Flags & CHECKXFLAG_PRINTALL) ||
- ((fd->fd_Flags & CHECKXFLAG_PRINTEXEC) && fib->fib_Size > 4
- && *((ULONG *)mem) == HUNK_HEADER))
- PrintCHKXFile(fd);
- ret = DoGetVirus(fd, mem, fib->fib_Size);
- }
- else
- FreeMem(mem, fib->fib_Size);
- }
- else
- {
- fd->fd_ArcFileFH = fh;
- PrintCHKXErr(fd, CHKXERR_NOMEMORYARC);
- ret = DoFileUnArchive(fd, 0, fib->fib_Size);
- }
- }
- else
- ret = CHKXERR_EXAMINEERR;
- Close(fh);
- }
- else
- ret = CHKXERR_OPENERR;
-
- FreeDosObject(DOS_FIB, fib);
- }
- else
- ret = CHKXERR_NOMEMORY;
-
- return ret;
- }
-
- /* for SAVE option: open parent directory and try to delete the directory
- we leave. This only succeeds, when the directory is empty. */
- static ULONG OpenParentDir(struct FileData *fd)
- {
- ULONG g;
- UBYTE name[300];
-
- if((g = fd->fd_SaveDirL))
- {
- NameFromLock(g, name, 300);
- fd->fd_SaveDirL = ParentDir(g);
- UnLock(g);
-
- DeleteFile(name);
- }
- else
- return -1;
-
- return fd->fd_SaveDirL;
- }
-
- /* Open a new subdirectory for SAVE option */
- static ULONG OpenNewDir(struct FileData *fd, STRPTR name)
- {
- ULONG g;
-
- if(fd->fd_SaveDirL)
- {
- g = CurrentDir(fd->fd_SaveDirL);
- if(!(fd->fd_SaveDirL = Lock(name, SHARED_LOCK)))
- if((fd->fd_SaveDirL = CreateDir(name)))
- ChangeMode(CHANGE_LOCK, fd->fd_SaveDirL, SHARED_LOCK);
- UnLock(CurrentDir(g));
- }
- else
- return -1;
-
- return fd->fd_SaveDirL;
- }
-
- static LONG DoGetVirus(struct FileData *fd, APTR buffer, ULONG buflength)
- {
- if(!buflength) /* restarted with empty file */
- return CHKXWARN_EMPTY;
-
- if(fd->fd_Flags & CHECKXFLAG_XVSLIB)
- {
- APTR mem;
-
- if((mem = AllocMem(buflength, MEMF_ANY)))
- {
- struct xvsFileInfo *fi;
- if((fi = (struct xvsFileInfo *) xvsAllocObject(XVSOBJ_FILEINFO)))
- {
- ULONG i;
- /* xvs may modify the buffer! */
- CopyMem(buffer, mem, buflength);
- fi->xvsfi_File = mem;
- fi->xvsfi_FileLen = buflength;
- i = xvsCheckFile(fi);
- if(i == XVSFT_DATAVIRUS)
- {
- PrintCHKXTxt(fd, "Data-Virus '%s'", fi->xvsfi_Name);
- ++fd->fd_NumVirus;
- }
- else if(i == XVSFT_FILEVIRUS)
- {
- PrintCHKXTxt(fd, "File-Virus '%s'", fi->xvsfi_Name);
- ++fd->fd_NumVirus;
- }
- else if(i == XVSFT_LINKVIRUS)
- {
- PrintCHKXTxt(fd, "Link-Virus '%s'", fi->xvsfi_Name);
- ++fd->fd_NumVirus;
- }
- xvsFreeObject(fi);
- }
- else
- PrintCHKXErr(fd, CHKXERR_NOVIRUS);
- FreeMem(mem, buflength);
- }
- else
- PrintCHKXErr(fd, CHKXERR_NOVIRUS);
-
- if(fd->fd_Flags & CHECKXFLAG_SECTORCHECK) /* && !(buflength & 0x1FF)*/
- PrintCHKXErr(fd, DoSectorCheck(fd, buffer, buflength, 0));
- }
-
- return DoFileUnArchive(fd, buffer, buflength);
- }
-
- static LONG DoSectorCheck(struct FileData *fd, APTR buffer, ULONG buflength, ULONG pos)
- {
- LONG err = 0;
- struct xvsSectorInfo *si;
-
- if((si = (struct xvsSectorInfo *) xvsAllocObject(XVSOBJ_SECTORINFO)))
- {
- ULONG i, j, k;
-
- j = buflength >> 9; /* divide by 512 */
- for(i = 0; i < j; ++i)
- {
- si->xvssi_Sector = ((STRPTR) buffer) + (i<<9);
- si->xvssi_Key = pos + i;
- k = xvsCheckSector(si);
- if(k == XVSST_DESTROYED)
- {
- ++fd->fd_NumSectors;
- PrintCHKXTxt(fd, "Sector %ld destroyed by '%s'", si->xvssi_Key, si->xvssi_Name);
- }
- else if(k == XVSST_INFECTED)
- {
- ++fd->fd_NumSectors;
- PrintCHKXTxt(fd, "Sector %ld infected by '%s'", si->xvssi_Key, si->xvssi_Name);
- }
- }
- xvsFreeObject(si);
- }
- else
- err = CHKXERR_NOSECTOR;
-
- return err;
- }
-
- /* For bootblocks */
- static ASM(LONG) OutHookCheckX(REG(a0, struct Hook *hook), REG(a1, struct xadHookParam *hp))
- {
- LONG i, j;
- STRPTR s;
- struct FileData *fd;
-
- fd = (struct FileData *) hook->h_Data;
- switch(hp->xhp_Command)
- {
- case XADHC_WRITE:
- j = hp->xhp_BufferSize;
- s = hp->xhp_BufferPtr;
- if((i = 1024-hp->xhp_DataPos) > j)
- i = j;
- if(i > 0)
- {
- CopyMem(s, fd->fd_Memory+hp->xhp_DataPos, i);
- hp->xhp_DataPos += i;
- j -= i;
- s += i;
- }
- if(hp->xhp_DataPos == 1024 && i > 0)
- {
- if(((fd->fd_Flags & CHECKXFLAG_XVSLIB) && (fd->fd_Flags & CHECKXFLAG_SECTORCHECK)))
- {
- i = DoSectorCheck(fd, fd->fd_Memory, 1024, 0);
- if(i)
- {
- PrintCHKXErr(fd, i);
- return 10000;
- }
- }
- else
- return 10000;
- }
- if(hp->xhp_DataPos >= 1024)
- {
- LONG k;
- while(j)
- {
- k = hp->xhp_DataPos & 0x1FF;
- if((i = 512-k) > j)
- i = j;
- CopyMem(s, fd->fd_Memory+1024+k, i);
- hp->xhp_DataPos += i;
- j -= i;
- s += i;
- if(!(hp->xhp_DataPos & 0x1FF))
- {
- i = DoSectorCheck(fd, fd->fd_Memory+1024, 512, (hp->xhp_DataPos>>9)-1);
- if(i)
- {
- PrintCHKXErr(fd, i);
- return 10000;
- }
- }
- }
- }
- case XADHC_INIT:
- case XADHC_FREE:
- case XADHC_ABORT:
- break;
- default: return XADERR_NOTSUPPORTED;
- }
-
- return 0;
- }
-
- /* To get real file size */
- static ASM(LONG) OutHookCheckXSize(REG(a0, struct Hook *hook), REG(a1, struct xadHookParam *hp))
- {
- switch(hp->xhp_Command)
- {
- case XADHC_WRITE:
- hp->xhp_DataPos += hp->xhp_BufferSize;
- hook->h_Data = (APTR) hp->xhp_DataPos;
- case XADHC_INIT:
- case XADHC_FREE:
- case XADHC_ABORT:
- break;
- default: return XADERR_NOTSUPPORTED;
- }
-
- return 0;
- }
-
- static void CheckArcFiles(struct FileData *fd, struct xadArchiveInfo *ai, ULONG disk)
- {
- struct xadFileInfo *fi;
- struct TagItem ti[6];
- LONG numloop = 0;
- STRPTR buf = 0;
-
- ti[0].ti_Tag = XAD_OUTMEMORY;
- ti[1].ti_Tag = XAD_OUTSIZE;
- ti[2].ti_Tag = XAD_ENTRYNUMBER;
- ti[3].ti_Tag = XAD_PROGRESSHOOK;
- ti[3].ti_Data = (ULONG) &breakhook;
- ti[4].ti_Tag = TAG_DONE;
-
- fi = ai->xai_FileInfo;
- while(!(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) && fi)
- {
- APTR dest;
-
- if(!(fi->xfi_Flags & (XADFIF_DIRECTORY|XADFIF_LINK)))
- {
- LONG err = 0;
- ULONG flags, size, linknum;
-
- flags = fd->fd_Flags;
- linknum = fd->fd_LinkNum;
- fd->fd_LinkNum = 0;
- if(!(fi->xfi_Flags & XADFIF_NOFILENAME))
- fd->fd_Flags &= ~CHECKXFLAG_NAMEPRINTED;
- fd->fd_Name = fi->xfi_FileName;
- fd->fd_RecurseDepth++;
- fd->fd_ArchiveDepth++;
-
- size = fi->xfi_Size;
- if(fi->xfi_Flags & XADFIF_NOUNCRUNCHSIZE)
- {
- struct Hook hook = {{0,0},(ULONG (*)()) OutHookCheckXSize, 0, 0};
- struct TagItem ti[5];
-
- ti[0].ti_Tag = XAD_OUTHOOK;
- ti[0].ti_Data = (ULONG) &hook;
- ti[1].ti_Tag = XAD_ENTRYNUMBER;
- ti[1].ti_Data = fi->xfi_EntryNumber;
- ti[2].ti_Tag = XAD_PROGRESSHOOK;
- ti[2].ti_Data = (ULONG) &breakhook;
- ti[3].ti_Tag = buf ? XAD_PASSWORD : TAG_IGNORE;
- ti[3].ti_Data = (ULONG) buf;
- ti[4].ti_Tag = TAG_DONE;
-
- if(!(err = (disk ? xadDiskFileUnArcA(ai, ti) : xadFileUnArcA(ai, ti))))
- size = (ULONG) hook.h_Data;
- }
-
- if(!size)
- {
- if(!err)
- err = CHKXWARN_EMPTY;
- }
- else if((dest = AllocMem(size, MEMF_PUBLIC)))
- {
- if(!(err = AddCrunchMemList(fd, dest, size)))
- {
- ti[0].ti_Data = (ULONG) dest;
- ti[1].ti_Data = size;
- ti[2].ti_Data = fi->xfi_EntryNumber;
- ti[4].ti_Tag = buf ? XAD_PASSWORD : TAG_IGNORE;
- ti[4].ti_Data = (ULONG) buf;
-
- if((err = disk ? xadDiskFileUnArcA(ai, ti) : xadFileUnArcA(ai, ti)))
- {
- if(disk)
- err = CHKXERR_READ;
- else
- err += XADERR_OFFSET;
- }
- else
- {
- if((fd->fd_Flags & CHECKXFLAG_PRINTALL) ||
- ((fd->fd_Flags & CHECKXFLAG_PRINTEXEC) && size > 4
- && *((ULONG *)dest) == HUNK_HEADER))
- PrintCHKXFile(fd);
- err = DoGetVirus(fd, dest, size);
- }
- FreeCrunchMemList(fd, dest);
- }
- else
- FreeMem(dest, size);
- }
- else
- err = CHKXERR_NOMEMORY;
-
- if((err == XADERR_OFFSET + XADERR_PASSWORD) && !numloop)
- {
- struct Library *xpkbase;
- if(fd->fd_Flags & CHECKXFLAG_ASKPWD && (xpkbase = OpenLibrary(XPKNAME, 4)))
- {
- if(buf)
- FreeMem(buf, 256);
- if((buf = (STRPTR) AllocMem(256, MEMF_ANY|MEMF_CLEAR)))
- {
- if(XpkPassRequestTags(XPK_PasswordBuf, buf, XPK_PassBufSize, 256,
- XPK_PassTitle, fd->fd_Name, TAG_DONE))
- {
- FreeMem(buf, 256); buf = 0; fi = fi->xfi_Next;
- }
- else
- {
- numloop = -1; err = 0;
- }
- }
-
- CloseLibrary(xpkbase);
- }
- }
-
- if(err)
- {
- if(fi->xfi_Flags & XADFIF_NOFILENAME)
- fd->fd_Flags &= ~CHECKXFLAG_NAMEPRINTED;
- PrintCHKXErr(fd, err);
- }
-
- --fd->fd_RecurseDepth;
- --fd->fd_ArchiveDepth;
- fd->fd_Flags = flags;
- fd->fd_LinkNum = linknum;
- }
- if(++numloop)
- {
- fi = fi->xfi_Next;
- numloop = 0;
- }
- else
- ++numloop;
- }
- if(buf)
- FreeMem(buf, 256);
- }
-
- /* Tests if a file is an archive. When yes, the archive is unarchived and
- the result files are scanned. Else DoFileUnLink is called.
- */
- static LONG DoFileUnArchive(struct FileData *fd, APTR buffer, ULONG buflength)
- {
- LONG err = 0;
- struct TagItem tih[2];
- struct xadArchiveInfo *ai;
-
- if(buffer) { tih[0].ti_Tag = XAD_INMEMORY; tih[0].ti_Data = (ULONG) buffer; }
- else { tih[0].ti_Tag = XAD_INFILEHANDLE; tih[0].ti_Data = (ULONG) fd->fd_ArcFileFH; }
- tih[1].ti_Tag = TAG_DONE;
-
- if((ai = (struct xadArchiveInfo *) xadAllocObject(XADOBJ_ARCHIVEINFO, 0)))
- {
- STRPTR arcname;
-
- arcname = fd->fd_Name;
- if(!xadGetInfo(ai, XAD_INSIZE, buflength, XAD_PROGRESSHOOK, &breakhook, TAG_MORE, tih))
- {
- if(ai->xai_Flags & XADAIF_FILECORRUPT)
- {
- ++fd->fd_CorruptedArchives;
- PrintCHKXTxt(fd, "%s (ARCHIVE, CORRUPTED)", ai->xai_Client->xc_ArchiverName);
- }
- else
- PrintCHKXTxt(fd, "%s (ARCHIVE)", ai->xai_Client->xc_ArchiverName);
-
- if(!(!(fd->fd_Flags & CHECKXFLAG_NOUNARCHIVE) && ai->xai_FileInfo ||
- !(fd->fd_Flags & CHECKXFLAG_NOUNTRACK) && ai->xai_DiskInfo))
- {
- if(buffer)
- err = DoFileUnLink(fd, buffer, buflength);
- }
- else if(!OpenNewDir(fd, FilePart(fd->fd_Name)))
- err = CHKXERR_OPENERR;
- else
- {
- if(!(fd->fd_Flags & CHECKXFLAG_NOUNARCHIVE) && ai->xai_FileInfo)
- CheckArcFiles(fd, ai, 0);
- if(!(fd->fd_Flags & CHECKXFLAG_NOUNTRACK) && ai->xai_DiskInfo)
- {
- STRPTR buf;
-
- /* reduce stacksize, as we have a recursive program */
- if((buf = (STRPTR) AllocMem(1024+512, MEMF_PUBLIC)))
- {
- ULONG flags;
- struct xadDiskInfo *di;
- struct xadArchiveInfo *aid;
- di = ai->xai_DiskInfo;
-
- flags = fd->fd_Flags;
- while(!(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) && di)
- {
- if(di->xdi_SectorSize != 512 || (di->xdi_TrackSectors != 11 &&
- di->xdi_TrackSectors != 22) || (!(di->xdi_Flags & XADDIF_NOHEADS) &&
- di->xdi_Heads != 2) || (!(di->xdi_Flags & XADDIF_NOCYLINDERS) &&
- di->xdi_Cylinders != 80))
- SPrintF(buf, "-disk image %ld", di->xdi_EntryNumber);
- else
- {
- if(!(di->xdi_Flags & (XADDIF_NOHIGHCYL|XADDIF_NOLOWCYL)) &&
- (di->xdi_LowCyl || di->xdi_HighCyl != 79))
- SPrintF(buf, "-disk image %ld (%s, %ld to %ld)",
- di->xdi_EntryNumber, di->xdi_TrackSectors == 22 ?
- "HD" : "DD", di->xdi_LowCyl, di->xdi_HighCyl);
- else
- SPrintF(buf, "-disk image %ld (%s)",
- di->xdi_EntryNumber, di->xdi_TrackSectors == 22 ? "HD" : "DD");
- }
-
- fd->fd_Flags &= ~CHECKXFLAG_NAMEPRINTED;
- fd->fd_Name = buf;
- PrintCHKXFile(fd);
-
- if(di->xdi_TextInfo)
- {
- struct xadTextInfo *ti;
- ULONG flags, i = 1, linknum;
-
- for(ti = di->xdi_TextInfo; ti; ti = ti->xti_Next)
- {
- if(ti->xti_Size && ti->xti_Text)
- {
- flags = fd->fd_Flags;
- fd->fd_Flags &= ~CHECKXFLAG_NAMEPRINTED;
- fd->fd_Flags |= CHECKXFLAG_NOFREEMEM;
- fd->fd_RecurseDepth++;
- linknum = fd->fd_LinkNum;
- fd->fd_LinkNum = 0;
- SPrintF(buf, "--infotext %ld (size %ld)", i, ti->xti_Size);
- if((fd->fd_Flags & CHECKXFLAG_PRINTALL) ||
- ((fd->fd_Flags & CHECKXFLAG_PRINTEXEC) && ti->xti_Size > 4
- && *((ULONG *)(ti->xti_Text)) == HUNK_HEADER))
- PrintCHKXFile(fd);
- PrintCHKXErr(fd, DoGetVirus(fd, ti->xti_Text, ti->xti_Size));
- --fd->fd_RecurseDepth;
- fd->fd_Flags = flags;
- fd->fd_LinkNum = linknum;
- }
- ++i;
- }
- }
-
- /* check bootblock here - special outhook for bootblock extraction */
- if(!di->xdi_LowCyl) /* boot check only, when first block! */
- {
- struct Hook hook = {{0,0},(ULONG (*)()) OutHookCheckX, 0};
- LONG i;
-
- fd->fd_Memory = buf;
- hook.h_Data = fd;
- i = xadDiskUnArc(ai, XAD_ENTRYNUMBER, di->xdi_EntryNumber,
- XAD_OUTHOOK, &hook, XAD_PROGRESSHOOK, &breakhook, TAG_DONE);
- if(!i || i == 10000) /* special hook return code! */
- {
- struct xvsBootInfo *bi;
-
- if((bi = (struct xvsBootInfo *) xvsAllocObject(XVSOBJ_BOOTINFO)))
- {
- bi->xvsbi_Bootblock = buf;
- if(xvsCheckBootblock(bi) == XVSBT_VIRUS)
- {
- PrintCHKXTxt(fd, "Boot-Virus '%s'", bi->xvsbi_Name);
- ++fd->fd_NumVirus;
- }
- xvsFreeObject(bi);
- }
- else
- PrintCHKXErr(fd, CHKXERR_NOBOOTVIRUS);
- }
- else
- PrintCHKXErr(fd, CHKXERR_NOBOOTVIRUS);
- }
-
- if((aid = (struct xadArchiveInfo *) xadAllocObject(XADOBJ_ARCHIVEINFO, 0)))
- {
- struct TagItem ti[4];
- struct xadClient *cl;
-
- ti[0].ti_Tag = XAD_INSIZE;
- ti[0].ti_Data = buflength;
- ti[1].ti_Tag = XAD_ENTRYNUMBER;
- ti[1].ti_Data = di->xdi_EntryNumber;
- ti[2].ti_Tag = XAD_PROGRESSHOOK;
- ti[2].ti_Data = (ULONG) &breakhook;
- ti[3].ti_Tag = TAG_MORE;
- ti[3].ti_Data = (ULONG) tih;
-
- if(!(err = xadGetDiskInfo(aid, XAD_NOEMPTYERROR, 1, XAD_PROGRESSHOOK, &breakhook,
- XAD_INDISKARCHIVE, ti, TAG_DONE)))
- {
- if(aid->xai_Flags & XADAIF_FILECORRUPT)
- {
- ++fd->fd_CorruptedArchives;
- PrintCHKXTxt(fd, "%s (FILESYSTEM, CORRUPTED)", aid->xai_Client->xc_ArchiverName);
- }
- else
- PrintCHKXTxt(fd, "%s (FILESYSTEM)", aid->xai_Client->xc_ArchiverName);
- CheckArcFiles(fd, aid, 1);
- cl = aid->xai_Client->xc_Next;
- xadFreeInfo(aid);
- while(cl) /* multiple filesystems */
- {
- if(!xadGetDiskInfo(aid, XAD_NOEMPTYERROR, 1, XAD_INDISKARCHIVE, ti,
- XAD_PROGRESSHOOK, &breakhook, XAD_STARTCLIENT, cl, TAG_MORE, TAG_DONE))
- {
- if(aid->xai_Flags & XADAIF_FILECORRUPT)
- {
- ++fd->fd_CorruptedArchives;
- PrintCHKXTxt(fd, "%s (FILESYSTEM, CORRUPTED)", aid->xai_Client->xc_ArchiverName);
- }
- else
- PrintCHKXTxt(fd, "%s (FILESYSTEM)", aid->xai_Client->xc_ArchiverName);
- CheckArcFiles(fd, aid, 1);
- cl = aid->xai_Client->xc_Next;
- xadFreeInfo(aid);
- }
- else
- cl = 0;
- }
- }
- else
- {
- if(err != XADERR_FILESYSTEM)
- PrintCHKXErr(fd, XADERR_OFFSET + err);
- err = 0;
- }
- xadFreeObjectA(aid, 0);
- }
-
- di = di->xdi_Next;
- } /* while */
- fd->fd_Flags = flags;
- FreeMem(buf, 1024+512);
- } /* AllocMem buffer */
- else
- err = CHKXERR_NOMEMORY;
- } /* is there a disk entry? */
- if(!OpenParentDir(fd))
- err = CHKXERR_OPENDIR;
- }
-
- xadFreeInfo(ai);
- } /* xadGetInfo */
- else if(!xadGetDiskInfo(ai, XAD_NOEMPTYERROR, 1, XAD_PROGRESSHOOK, &breakhook,
- XAD_INSIZE, buflength, TAG_MORE, tih))
- {
- struct xadClient *cl;
- ULONG isvalid = 1;
-
- if(ai->xai_Flags & XADAIF_FILECORRUPT)
- {
- ++fd->fd_CorruptedArchives;
- PrintCHKXTxt(fd, "%s (FILESYSTEM, CORRUPTED)", ai->xai_Client->xc_ArchiverName);
- }
- else
- PrintCHKXTxt(fd, "%s (FILESYSTEM)", ai->xai_Client->xc_ArchiverName);
-
- if(fd->fd_Flags & CHECKXFLAG_NOUNTRACK)
- {
- if(buffer)
- err = DoFileUnLink(fd, buffer, buflength);
- }
- else if(!OpenNewDir(fd, FilePart(fd->fd_Name)))
- err = CHKXERR_OPENERR;
- else
- {
- CheckArcFiles(fd, ai, 1);
- while(isvalid && (cl = ai->xai_Client->xc_Next))
- {
- xadFreeInfo(ai);
- if(!xadGetDiskInfo(ai, XAD_NOEMPTYERROR, 1, XAD_PROGRESSHOOK, &breakhook,
- XAD_INSIZE, buflength, XAD_STARTCLIENT, cl, TAG_MORE, tih))
- {
- if(ai->xai_Flags & XADAIF_FILECORRUPT)
- {
- ++fd->fd_CorruptedArchives;
- PrintCHKXTxt(fd, "%s (FILESYSTEM, CORRUPTED)", ai->xai_Client->xc_ArchiverName);
- }
- else
- PrintCHKXTxt(fd, "%s (FILESYSTEM)", ai->xai_Client->xc_ArchiverName);
- CheckArcFiles(fd, ai, 1);
- }
- else
- isvalid = 0;
- }
- if(!OpenParentDir(fd))
- err = CHKXERR_OPENDIR;
- }
- if(isvalid)
- xadFreeInfo(ai);
- }
- else if(buffer)
- err = DoFileUnLink(fd, buffer, buflength);
-
- fd->fd_Name = arcname;
- xadFreeObjectA(ai, 0);
- }
- else
- err = CHKXERR_NOMEMORY;
-
- return err;
- }
-
- /* Tries to unlink a file. When the file was linked, we call DoGetVirus
- for the two parts to check if they may be archives, else we call
- DoFileUnCrunch.
- */
- static LONG DoFileUnLink(struct FileData *fd, APTR buffer, ULONG buflength)
- {
- LONG ret = CHKXERR_NOMEMORY;
- struct xfdLinkerInfo *xli;
-
- if((xli = (struct xfdLinkerInfo *) xfdAllocObject(XFDOBJ_LINKERINFO)))
- {
- xli->xfdli_Buffer = buffer;
- xli->xfdli_BufLen = buflength;
- if(xfdRecogLinker(xli))
- {
- PrintCHKXTxt(fd, xli->xfdli_LinkerName);
- if(fd->fd_Flags & CHECKXFLAG_NOUNLINK)
- ret = DoFileUnCrunch(fd, buffer, buflength);
- else if(xfdUnlink(xli))
- {
- ULONG flags;
- fd->fd_Flags |= CHECKXFLAG_LINKED;
- ++fd->fd_RecurseDepth;
- ++fd->fd_LinkNum;
- flags = fd->fd_Flags;
- fd->fd_Flags |= CHECKXFLAG_NOFREEMEM;
- PrintCHKXErr(fd, DoGetVirus(fd, xli->xfdli_Save1,
- xli->xfdli_SaveLen1));
- fd->fd_Flags = flags; /* CHECKXFLAG_NOFREEMEM is cleared */
- PrintCHKXErr(fd, DoGetVirus(fd, xli->xfdli_Save2,
- xli->xfdli_SaveLen2));
- ret = 0;
- --fd->fd_RecurseDepth;
- }
- else
- ret = XFDERR_OFFSET + xli->xfdli_Error;
- }
- else
- ret = DoFileUnCrunch(fd, buffer, buflength);
-
- xfdFreeObject(xli);
- }
- return ret;
- }
-
- /* Tries to decrunch a file. When it is crunched, we decrunch it and call
- DoGetVirus to start the loop again. Else we call unstripping.
- */
- static LONG DoFileUnCrunch(struct FileData *fd, APTR buffer, ULONG buflength)
- {
- LONG ret = CHKXERR_NOMEMORY;
- struct xfdBufferInfo *xbi;
-
- if((xbi = (struct xfdBufferInfo *) xfdAllocObject(XFDOBJ_BUFFERINFO)))
- {
- xbi->xfdbi_SourceBuffer = buffer;
- xbi->xfdbi_SourceBufLen = buflength;
- xbi->xfdbi_Flags = XFDFF_RECOGEXTERN;
- if(xfdRecogBuffer(xbi))
- {
- struct Library *xpkbase;
- STRPTR buf = 0;
- ULONG buflen = 0;
-
- PrintCHKXTxt(fd, xbi->xfdbi_PackerFlags & XFDPFF_ADDR ? "%s (ADDRESS)" :
- "%s", xbi->xfdbi_PackerName);
-
- if(fd->fd_Flags & CHECKXFLAG_ASKPWD && (xpkbase =
- OpenLibrary(XPKNAME, 4)))
- {
- ASSIGN_XPK
- if(xbi->xfdbi_PackerFlags & XFDPFF_PASSWORD)
- {
- buflen = (xbi->xfdbi_MaxSpecialLen == 0xFFFF) ? 256 :
- xbi->xfdbi_MaxSpecialLen;
- if((buf = (STRPTR) AllocMem(buflen, MEMF_ANY|MEMF_CLEAR)))
- {
- if(!XpkPassRequestTags(XPK_PasswordBuf, buf, XPK_PassTitle, fd->fd_Name,
- XPK_PassBufSize, buflen, TAG_DONE))
- xbi->xfdbi_Special = buf;
- }
- }
- else if(xbi->xfdbi_PackerFlags & XFDPFF_KEY16)
- {
- if(!XpkPassRequestTags(XPK_Key16BitPtr, &buflen, XPK_PassTitle, fd->fd_Name, TAG_DONE))
- xbi->xfdbi_Special = &buflen;
- }
- else if(xbi->xfdbi_PackerFlags & XFDPFF_KEY32)
- {
- if(!XpkPassRequestTags(XPK_Key32BitPtr, &buflen, XPK_PassTitle, fd->fd_Name, TAG_DONE))
- xbi->xfdbi_Special = &buflen;
- }
- CloseLibrary(xpkbase);
- }
- if(fd->fd_Flags & CHECKXFLAG_NODECRUNCH)
- ret = DoFileStrip(fd, buffer, buflength);
- else if(xfdDecrunchBuffer(xbi))
- {
- if((xbi->xfdbi_PackerFlags & XFDPFF_ADDR) &&
- !(fd->fd_Flags & CHECKXFLAG_ADDRESS))
- {
- fd->fd_Flags |= CHECKXFLAG_ADDRESS;
- PrintCHKXErr(fd, SaveUncrFile(fd, buffer, buflength));
- }
- fd->fd_Flags |= CHECKXFLAG_CRUNCHED;
- FreeCrunchMemList(fd, buffer);
- ++fd->fd_RecurseDepth;
- if(!(ret = AddCrunchMemList(fd, xbi->xfdbi_TargetBuffer,
- xbi->xfdbi_TargetBufLen)))
- {
- PrintCHKXErr(fd, DoGetVirus(fd, xbi->xfdbi_TargetBuffer,
- xbi->xfdbi_TargetBufSaveLen));
- }
- else
- FreeMem(xbi->xfdbi_TargetBuffer, xbi->xfdbi_TargetBufLen);
- --fd->fd_RecurseDepth;
- }
- else
- ret = XFDERR_OFFSET + xbi->xfdbi_Error;
-
- if(buf)
- FreeMem(buf, buflen);
- }
- else
- ret = DoFileStrip(fd, buffer, buflength);
-
- xfdFreeObject(xbi);
- }
- return ret;
- }
-
- /* Tries to strip useless hunks in a file. When there are some, we remove
- them and call DoGetVirus to start the loop again. Else we finish.
- When either unlinking or uncrunching happend in before loops, we may
- save the file when there was SAVE option.
- */
- static LONG DoFileStrip(struct FileData *fd, APTR buffer, ULONG buflength)
- {
- LONG ret = 0;
- ULONG reslength = buflength;
-
- if(*((ULONG *) buffer) == 0x000003F3 && !(fd->fd_Flags &
- CHECKXFLAG_NOSTRIP))
- xfdStripHunks(buffer, buflength, &reslength,
- XFDSHF_NAME|XFDSHF_SYMBOL|XFDSHF_DEBUG);
- /* errors are not interpreted */
-
- if(buflength > reslength)
- {
- fd->fd_Flags |= CHECKXFLAG_STRIPPED;
- PrintCHKXTxt(fd, "%ld bytes stripped", buflength-reslength);
- ret = DoGetVirus(fd, buffer, reslength);
- }
- else if(!(fd->fd_Flags & CHECKXFLAG_ADDRESS))
- ret = SaveUncrFile(fd, buffer, buflength);
-
- FreeCrunchMemList(fd, buffer);
-
- return ret;
- }
-
- /* Print file name */
- static void PrintCHKXFile(struct FileData *fd)
- {
- STRPTR name = fd->fd_Name;
- UBYTE i;
-
- if(fd->fd_Flags & CHECKXFLAG_DEBUG)
- {
- for(i = 0; i < fd->fd_ArchiveDepth; ++i)
- KPutC('*');
- KPrintf("%s\n", name);
- }
-
- if(fd->fd_LogFileFH)
- {
- for(i = 0; i < fd->fd_ArchiveDepth; ++i)
- FPutC(fd->fd_LogFileFH, '*');
- FPrintf(fd->fd_LogFileFH, "%s\n", name);
- }
- if(!(fd->fd_Flags & CHECKXFLAG_QUIET))
- {
- for(i = 0; i < fd->fd_ArchiveDepth; ++i)
- FPutC(Output(), '*');
- Printf("%s\n", name);
- }
- fd->fd_Flags |= CHECKXFLAG_NAMEPRINTED;
- }
-
- static void PrintCHKXErr(struct FileData *fd, LONG err)
- {
- if(err)
- {
- STRPTR txt = 0, txt2;
-
- if(err > XFDERR_OFFSET)
- {
- ++fd->fd_XFDErrors;
- txt2 = "XFD-Error %ld: %s";
- err -= XFDERR_OFFSET;
- txt = xfdGetErrorText(err);
- }
- else if(err > XADERR_OFFSET)
- {
- ++fd->fd_XADErrors;
- txt2 = "XAD-Error %ld: %s";
- err -= XADERR_OFFSET;
- txt = xadGetErrorText(err);
- }
- else if(err > CHXWARN_OFFSET)
- {
- ++fd->fd_CHKXWarnings;
- txt2 = "CheckX-Warning %ld: %s";
- switch(err)
- {
- case CHKXWARN_NOVIRUS: txt = "Virus-Checking disabled!"; break;
- case CHKXWARN_XVSSELFTEST:txt = "The xvs.library is modified, maybe the system is virus infected!"; break;
- case CHKXWARN_MEMVIRUS: txt = "Your system memory was virus infected!"; break;
- case CHKXWARN_EMPTY: txt = "file is empty"; break;
- }
- err -= CHXWARN_OFFSET;
- }
- else
- {
- ++fd->fd_CHKXErrors;
- txt2 = "CheckX-Error %ld: %s";
- switch(err)
- {
- case CHKXERR_NOMEMORY: txt = "not enough memory"; break;
- case CHKXERR_EXAMINEERR: txt = "examining failed"; break;
- case CHKXERR_OPENERR: txt = "opening file failed"; break;
- case CHKXERR_READ: txt = "reading failed"; break;
- case CHKXERR_SCANERR: txt = "directory scan failed"; break;
- case CHKXERR_BREAK: txt = "user break"; break;
- case CHKXERR_OPENDIR: txt = "opening directory failed"; break;
- case CHKXERR_RESOURCE: txt = "needed resource not available"; break;
- case CHKXERR_NOBOOTVIRUS: txt = "could not check for bootblock virus"; break;
- case CHKXERR_WRITE: txt = "writing failed"; break;
- case CHKXERR_NOVIRUS: txt = "could not check for virus"; break;
- case CHKXERR_NOMEMORYARC: txt = "not enough memory for full tests"; break;
- case CHKXERR_NOSECTOR: txt = "could not check sectors"; break;
- }
- }
-
- PrintCHKXTxt(fd, txt2, err, txt);
- }
- }
-
- /* Print type text */
- static void PrintCHKXTxt(struct FileData *fd, STRPTR txt, ...)
- {
- UBYTE i;
-
- if(!(fd->fd_Flags & CHECKXFLAG_NAMEPRINTED))
- PrintCHKXFile(fd);
-
- if(fd->fd_Flags & CHECKXFLAG_DEBUG)
- {
- for(i = 0; i < fd->fd_RecurseDepth; ++i)
- KPutC(' ');
- RawDoFmt(txt, &txt+1, (void (*)()) KPutC, 0);
- KPutC('\n');
- }
-
- if(fd->fd_LogFileFH)
- {
- for(i = 0; i < fd->fd_RecurseDepth; ++i)
- FPutC(fd->fd_LogFileFH, ' ');
- VFPrintf(fd->fd_LogFileFH, txt, &txt+1);
- FPutC(fd->fd_LogFileFH, '\n');
- Flush(fd->fd_LogFileFH);
- }
-
- if(!(fd->fd_Flags & CHECKXFLAG_QUIET))
- {
- for(i = 0; i < fd->fd_RecurseDepth; ++i)
- FPutC(Output(), ' ');
- VPrintf(txt, &txt+1);
- FPutC(Output(), '\n');
- }
- }
-
- /* Add memory to the memory list. */
- static LONG AddCrunchMemList(struct FileData *fd, APTR reg, ULONG size)
- {
- struct CrunchMemList *ml;
-
- if((ml = (struct CrunchMemList *) AllocMem(sizeof(struct CrunchMemList),
- MEMF_ANY)))
- {
- ml->cml_Next = fd->fd_MemList;
- ml->cml_MemoryRegion = reg;
- ml->cml_MemorySize = size;
- fd->fd_MemList = ml;
- return 0;
- }
-
- return CHKXERR_NOMEMORY;
- }
-
- /* Free memory from the memory list. */
- static void FreeCrunchMemList(struct FileData *fd, APTR reg)
- {
- struct CrunchMemList mc, *ml = &mc;
-
- if(fd->fd_Flags & CHECKXFLAG_NOFREEMEM)
- return;
-
- for(mc.cml_Next = fd->fd_MemList; ml; ml = ml->cml_Next)
- {
- if(ml->cml_Next->cml_MemoryRegion == reg)
- {
- struct CrunchMemList *m;
- m = ml->cml_Next;
- ml->cml_Next = m->cml_Next;
- FreeMem(m->cml_MemoryRegion, m->cml_MemorySize);
- FreeMem(m, sizeof(struct CrunchMemList));
- }
- }
-
- fd->fd_MemList = mc.cml_Next;
- }
-
- /* Save file, when SAVE option and file was crunched or linked. */
- static LONG SaveUncrFile(struct FileData *fd, APTR buf, ULONG size)
- {
- BPTR filefh, cd;
- LONG ret = 0, i = 0;
- UBYTE name[50];
- UBYTE nbuf[256];
-
- if(!(fd->fd_SaveDirL && (fd->fd_Flags & CHKXSAVEFLAGS)))
- return 0;
-
- SPrintF(name, (fd->fd_LinkNum ? "%s.%ld" : "%s"), FilePart(fd->fd_Name),
- fd->fd_LinkNum++);
-
- cd = CurrentDir(fd->fd_SaveDirL);
-
- while(!ret && name[i])
- {
- for(;name[i] && name[i] != '/'; ++i)
- nbuf[i] = name[i];
- if(name[i] == '/')
- {
- nbuf[i] = 0;
- if((filefh = Lock(nbuf, SHARED_LOCK)))
- UnLock(filefh);
- else
- {
- if((filefh = CreateDir(nbuf)))
- UnLock(filefh);
- else
- ret = CHKXERR_OPENERR;
- }
- nbuf[i] = name[i];
- ++i;
- }
- }
-
- if(!ret)
- {
- if((filefh = Open(name, MODE_NEWFILE)))
- {
- if(Write(filefh, buf, size) != size)
- ret = CHKXERR_WRITE;
- Close(filefh);
- }
- else
- ret = CHKXERR_OPENERR;
- }
-
- CurrentDir(cd);
-
- return ret;
- }
-
- #ifdef __SASC
- #undef SysBase
- #define SysBase sysbase
- #endif
-
- static ASM(LONG) BreakHookCheckX(void)
- {
- return (SetSignal(0L,0L) & SIGBREAKF_CTRL_C) ? 0 : XADPIF_OK;
- }
- static const struct Hook breakhook = {{0,0},(ULONG (*)()) BreakHookCheckX, 0};
-
- static ASM(void) SPrintF_putfunc(REG(d0, UBYTE data), REG(a3, STRPTR *a))
- {
- *((*a)++) = data;
- }
-
- static void SPrintF(STRPTR buf, STRPTR format, ...)
- {
- STRPTR buf2 = buf;
- RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
- (void(*)()) SPrintF_putfunc, &buf2);
- }
-
- static ASM(void) KPutC(REG(d0, ULONG c))
- {
- RawPutChar(c);
- }
-
- static void KPrintf(STRPTR fmt, ...)
- {
- RawDoFmt(fmt, &fmt + 1, (void (*)()) KPutC, 0);
- }
-
-